//
// Created by Administrator on 2020/7/9.
//T6章:数组、指针与字符串(2)
//指针与函数
//1-以指针作为函数参数
//为什么需要用指针作参数？
//a.需要数据双向传递时(引用野结衣达到此效果)
//b.需要传递一组数据,只传首地址运行效率比较高
//eg:读入是三个浮点数,将整数部分与小数部分分别输出
/*
#include <iostream>
using namespace std;
//将实数x分成整数部分和小数部分,形参intpart、fracpart是指针
void splitFloat(float x,int *intPart,float *fracPart)
{
    *intPart= static_cast<int>(x);//取x的整数部分
    *fracPart=x-*intPart;//取x的小数部分
}

int main()
{
    cout<<"Enter 3 float point numbers:"<<endl;
    for(int i=0;i<3;i++){
        float x,f;
        int n;
        cin>>x;
        splitFloat(x,&n,&f);//变量地址作为实参(&n即取n的地址 &f即取f的地址)
        cout<<"Integer Part="<<n<<" Fraction Part="<<f<<endl;
    }
    return 0;
}
*/
//指向常量的指针作形参
#include <iostream>
using namespace std;
const int N=6;
void print(const int *p,int n);
int main()
{
    int array[N];
    for(int i=0;i<N;i++)
        cin>>array[i];
    print(array,N);
    return  0;
}
void print(const int *p,int n)//指向常量的指针 const
{
    cout<<"{"<<*p;
    for(int i=1;i<n;i++)
        cout<<","<<*(p+i);
    cout<<"}"<<endl;
}

//2-指针类型的函数
//即返回值是指针的函数
//指针函数的定义类型:
//存储类型 数据类型 *函数名()
//{//函数体语句
//}
//注意:不要将非静态局部地址用作函数的返回值
//eg:错误的实例
int main()
{
    int* function();
    int* ptr=function();
    *ptr=5;//危险的访问!
    return 0;
}
int* function()
{
    int local=0;//非静态局部变量作用域和寿命都仅限于本函数体内
    return &local;
}//函数运行结束时,变量local被释放

//注意:返回的指针要确保在主调函数中是有效、合法的地址
//eg:正确的实例
#include <iostream>
using namespace std;
int main()
{
    int array[10];//函数中定义的数组
    int* search(int* s,int num);
    for(int i=0;i<10;i++)
        cin>>array[i];
    int* Zero_ptr=search(array,10);//将函数中数组的首地址传给子函数
    return 0;
}
int* search(int* a,int num)//指针a指向主函数中定义的数组
{
    for(int i=0;i<num;i++)
        if(a[i]==0)
            return &a[i];//返回的地址指向的元素是在主函数中定义的
}//函数运行结束时,a[i]的地址仍有效

//注意:在子函数中通过动态内存分配new操作取得的内存地址返回给主函数是合法有效的,
//但是内存分配和释放不在同一级别,要注意不能忘记释放,避免内存泄露
//eg:
#include <iostream>
using namespace std;

int main()
{
    int* new_int_var();
    int* intptr=new_int_var();
    *intptr=5;//访问的是合法有效的地址
    delete intptr;//如果忘记在这里释放,会造成内存泄漏
    return 0;

}
int* new_int_var()
{
    int* p=new int();
    return p;//返回的地址指向的是动态分配的空间
}//函数运行结束时,p中的地址仍有效


//3-指向函数的指针
//定义形式:存储类型 数据类型 (*函数指针名)();
//含义:函数指针指向的是程序代码存储区

//函数指针的典型用途:实现函数回调
//a.通过函数指针调用的函数:例如将函数的指针作为采纳火速传递给一个函数,使得在处理相似事件的时候
//  可以灵活的使用不同的方法。
//b.调用者不关心谁是调用者:需知道存在一个具有特定原型和限制条件的被调用函数。
//例子:
//eg:编写一个计算函数compute,对两个整数进行各种计算。
//   有一个形参为指向具体算法函数的指针,根据不同的实参函数,用不同的算法进行计算。
//   编写三个函数:求两个整数的最大值、最小值、和。分别用这三个函数作为实参,测试compute函数。

#include <iostream>
using namespace std;
int compute(int a,int b,int(*func)(int,int)){return func(a,b);}
int max(int a,int b){return ((a>b)?a:b);}//求最大值
int min(int a,int b){return ((a<b)?a:b);}//求最小值
int sum(int a,int b){return a+b;}//求和

int main()
{
    int a,b,res;
    cout<<"Please input integer a:";cin>>a;
    cout<<"Please input integer b:";cin>>b;

    res=compute(a,b,&max);
    cout<<"Max of"<<a<<"and"<<b<<"is"<<res<<endl;
    res=compute(a,b,&min);
    cout<<"Min of"<<a<<"and"<<b<<"is"<<res<<endl;
    res=compute(a,b,&sum);
    cout<<"Sum of"<<a<<"and"<<b<<"is"<<res<<endl;

    return 0;
}




